package com.linkallcloud.log.web.aop;

import java.lang.reflect.Method;
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.linkallcloud.cache.redis.box.RedisTokenBox;
import com.linkallcloud.core.annotation.LacLog;
import com.linkallcloud.core.lang.Mirror;
import com.linkallcloud.core.lang.Strings;
import com.linkallcloud.core.www.ISessionBUser;
import com.linkallcloud.core.www.ISimpleUser;
import com.linkallcloud.core.www.utils.WebUtils;
import com.linkallcloud.log.core.aop.LogAspect;
import com.linkallcloud.log.web.domain.BusiWebLog;
import com.linkallcloud.web.utils.Controllers;

public abstract class BusiWebLogAspect<T extends BusiWebLog, U extends ISimpleUser> extends LogAspect<T> {

    protected Mirror<U> mirror;

    @Autowired
    private RedisTokenBox tokenBox;

    @SuppressWarnings("unchecked")
    public BusiWebLogAspect() {
        super();
        try {
            mirror = Mirror.me((Class<U>) Mirror.getTypeParams(getClass())[1]);
        } catch (Throwable e) {
            systemErrorLog(0, null, null, null, e, "Fail to get TypeParams for self!");
        }
    }

    @SuppressWarnings("unchecked")
    public BusiWebLogAspect(boolean storageAll) {
        super(storageAll);
        try {
            mirror = Mirror.me((Class<U>) Mirror.getTypeParams(getClass())[1]);
        } catch (Throwable e) {
            systemErrorLog(0, null, null, null, e, "Fail to get TypeParams for self!");
        }
    }

    protected Class<U> getSessinoUserClass() {
        return (null == mirror) ? null : mirror.getType();
    }

    protected ISimpleUser getSessionUser() {
        HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return Controllers.getSessionUser(request, tokenBox, getSessinoUserClass());
    }

    @Override
    protected void subclassDealLogs(T operatelog, JoinPoint joinPoint, Class<?> clzz, Method method, LacLog logAnnot) {
        if (clzz.getAnnotation(Controller.class) != null) {
            ISimpleUser su = getSessionUser();
            operatelog.setOperator(su);
            if (su instanceof ISessionBUser) {
                ISessionBUser ssu = (ISessionBUser) su;
                operatelog.setOrgId(ssu.companyId());
                operatelog.setOrgType(ssu.getUserType());
            }

            /* busi */
            if (logAnnot != null) {
                operatelog.setOperateDesc(
                        dealStringTtemplate(true, logAnnot.desc(), joinPoint, method, new HashMap<String, Object>() {
                            private static final long serialVersionUID = 1L;
                            {
                                put("tid", operatelog.getTid());
                                put("su", su);
                                put("user", su);
                                put("saveTag", operatelog.getSaveTag());
                            }
                        }));
            }

            if (Strings.isBlank(operatelog.getOperateDesc())) {
                operatelog.setOperateDesc("日志信息");
            }

            HttpServletRequest request =
                    ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            operatelog.setIp(WebUtils.getIpAddress(request));
            operatelog.setUrl(request.getRequestURI());
            operatelog.setUa(request.getHeader("User-Agent"));
        }
    }

}
